#include "StdAfx.h"
#include "SampleBuffer.h"
#include "WaveSample.h"

SampleBuffer::SampleBuffer(void)
{
	chunkSize = 0;
	bufferCount = 0;
	nullSample = NULL;
}

SampleBuffer::~SampleBuffer(void)
{
	Reset();
	if(nullSample) delete nullSample;
}

void SampleBuffer::Initialize(int chunkSize, int bufferCount, bool silenceWhenEmpty)
{
	this->chunkSize = chunkSize;
	this->bufferCount = bufferCount;
	if(silenceWhenEmpty)
	{
		nullSample = new Sample(chunkSize);
		for(int i=0; i<chunkSize; i++)
		{
			nullSample->data[i] = 0;
		}
	}
}

int SampleBuffer::Size()
{
	return buffers.size();
}

void SampleBuffer::Reset()
{
	while(buffers.size()) {
		Sample* sample = buffers.front();
		buffers.pop();
		delete sample;
	}
}

void SampleBuffer::Write(Sample* sample)
{
	Sample* copy = sample->Copy(1.0, 1);
	while(buffers.size()>=bufferCount)
	{
		Sleep(10);
	}
	mutex.Lock();
	buffers.push(copy);
	mutex.Unlock();
}

Sample* SampleBuffer::Read()
{
	if(buffers.size()==0 && nullSample)
	{
		return nullSample->Copy(1.0, 0);
	}

	while(buffers.size()==0)
	{
		Sleep(1);
	}
	mutex.Lock();
	Sample* sample = buffers.front();
	buffers.pop();
	mutex.Unlock();
	return sample;	
}




SampleBuffer2::SampleBuffer2(void)
{
	chunkSize = 0;
	bufferCount = 0;
	nullSample = NULL;
}

SampleBuffer2::~SampleBuffer2(void)
{
	while(writtenSamples.size())
	{
		Sample* s = writtenSamples.front();
		writtenSamples.pop();
		delete s;
	}
	while(idleSamples.size())
	{
		Sample* s = idleSamples.front();
		idleSamples.pop();
		delete s;
	}
	if(nullSample) delete nullSample;
}

void SampleBuffer2::Initialize(int chunkSize, int bufferCount, bool silenceWhenEmpty)
{
	this->chunkSize = chunkSize;
	this->bufferCount = bufferCount;
	if(silenceWhenEmpty)
	{
		nullSample = new Sample(chunkSize);
		for(int i=0; i<chunkSize; i++)
		{
			nullSample->data[i] = 0;
		}
	}
	for(int i=0; i<bufferCount; i++)
	{
		Sample* s = new Sample(chunkSize);
		idleSamples.push(s);
	}
	active = true;
}


int SampleBuffer2::Size()
{
	return bufferCount;
}

void SampleBuffer2::SetActive(bool active)
{
	this->active = active;
}
bool SampleBuffer2::IsActive()
{
	return active;
}

void SampleBuffer2::Reset()
{
	active = false;
	while(writtenSamples.size())
	{
		Sample* s = writtenSamples.front();
		writtenSamples.pop();
		idleSamples.push(s);
	}
}

void SampleBuffer2::Write(Sample* sample)
{
	if(!active)return;
	while(idleSamples.size()==0)
	{
		Sleep(1);
	}
	mutex.Lock();
	Sample* ourSample = idleSamples.front();
	idleSamples.pop();
	for(int i=0; i<ourSample->length; i++)
	{
		ourSample->data[i] = sample->data[i];
	}
	writtenSamples.push(ourSample);
	mutex.Unlock();
}

Sample* SampleBuffer2::Read()
{
	if(!active)return NULL;
	Sample* ourSample = NULL;
	if(nullSample && writtenSamples.size()==0)
	{
		return nullSample;
	}
	while(writtenSamples.size()==0)
	{
		Sleep(1);
	}
	mutex.Lock();
	ourSample = writtenSamples.front();
	writtenSamples.pop();
	mutex.Unlock();
	return ourSample;	
}

void SampleBuffer2::Recycle(Sample* sample)
{
	mutex.Lock();
	idleSamples.push(sample);
	mutex.Unlock();
}
